import { Component, OnInit } from '@angular/core';
import { StudentsService } from './students.service';
import { StudentsGetDto } from './dto/students.get.dto';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { CreateStudentDto } from './dto/create-student.dto';
import { NzMessageService } from 'ng-zorro-antd/message';
import { StudentsDeleteDto } from './dto/students.delete.dto';
import { SendMessageDto } from './dto/send-message.dto';

@Component({
  selector: 'app-students',
  templateUrl: './students.component.html',
  styleUrls: ['./students.component.css']
})
export class StudentsComponent implements OnInit {
  students: StudentsGetDto[];
  studentsBak: StudentsGetDto[];
  // 表格每一行，是否展开
  mapOfExpandData: { [key: string]: boolean } = {};
  // 表格每一行，复选框是否选中
  mapOfCheckedId: { [key: string]: boolean } = {};
  // 添加学生抽屉是否显示
  createStudentDrawerVisible = false;
  // 编辑学生抽屉是否显示
  updateStudentDrawerVisible = false;
  // 发送消息抽屉是否显示
  sendMessageDrawerVisible = false;
  // 添加学生表单
  createStudentForm: FormGroup;
  // 编辑学生表单
  updateStudentForm: FormGroup;
  // 发送消息表单
  sendMessageForm: FormGroup;
  // 所有显示的数据是否全部选中
  isAllDisplayDataChecked = false;
  // 是否为不确定状态
  isIndeterminate = false;
  // 当前页面数据
  listOfDisplayData: StudentsGetDto[];
  // 搜索值
  searchValue: string;
  // 班级名
  className = 'D自集成191';

  constructor(
    private studentsService: StudentsService,
    private formBuilder: FormBuilder,
    private message: NzMessageService
  ) {
    this.createStudentForm = this.formBuilder.group({
      name: ['唐金健', [Validators.required]],
      studentID: ['234160501', [Validators.required]],
      mail: ['1271115696@qq.com', [Validators.required]],
      sex: ['男', [Validators.required]],
      nation: ['汉', [Validators.required]],
      birthdate: ['1998-01-14', [Validators.required]],
      identityCard: ['320123199801145011', [Validators.required]],
      className: ['D自集成162', [Validators.required]],
      politicsStatus: ['共青团员', [Validators.required]],
      dorm: ['北十B526', [Validators.required]],
      highSchool: ['南京六合中等专业学校', [Validators.required]],
      adress: [
        '南京市六合区雄州街道王桥路188号桥西苑11栋2908室',
        [Validators.required]
      ],
      tel: ['17512562019', [Validators.required]]
    });

    this.updateStudentForm = this.formBuilder.group({
      name: ['宋思泉', [Validators.required]],
      studentID: ['234160501', [Validators.required]],
      mail: ['1271115696@qq.com', [Validators.required]],
      sex: ['男', [Validators.required]],
      nation: ['汉', [Validators.required]],
      birthdate: ['1998-01-14', [Validators.required]],
      identityCard: ['320123199801145011', [Validators.required]],
      className: ['D自集成162', [Validators.required]],
      politicsStatus: ['共青团员', [Validators.required]],
      dorm: ['北十B526', [Validators.required]],
      highSchool: ['南京六合中等专业学校', [Validators.required]],
      adress: [
        '南京市六合区雄州街道王桥路188号桥西苑11栋2908室',
        [Validators.required]
      ],
      tel: ['17512562019', [Validators.required]]
    });

    this.sendMessageForm = this.formBuilder.group({
      subject: ['今天也是充满希望的一天', [Validators.required]],
      text: ['月色与雪色之间，你是第三种绝色', [Validators.required]]
    });
  }

  ngOnInit() {
    this.fetchStudents();
  }

  /**
   * 拉取学生数据
   */
  fetchStudents() {
    this.studentsService
      .getStudents(this.className ? { className: this.className } : {})
      .subscribe(studentsGetDto => {
        this.students = [...studentsGetDto];
        this.studentsBak = [...studentsGetDto];
      });
  }

  setClassName(className: string) {
    this.className = className;
    this.fetchStudents();
  }

  /**
   * 向学生数据和备份数据的开头，增加一个元素
   * @param studentsPostDto 待增加的学生
   */
  unshiftStudents(studentsPostDto: StudentsGetDto) {
    this.students.unshift(studentsPostDto);
    this.studentsBak.unshift(studentsPostDto);
  }

  /**
   * 删除指定的学生
   * @param _id 学生数据的唯一 _id
   */
  // tslint:disable-next-line: variable-name
  deleteRow(_id: string) {
    this.studentsService
      .deleteStudent(_id)
      .subscribe((studentsDeleteDto: StudentsDeleteDto) => {
        this.fetchStudents();
        this.message.create('success', `删除学生成功`);
      });
  }

  /**
   * 打开添加学生的抽屉
   */
  openCreateStudentDrawer(): void {
    this.createStudentDrawerVisible = true;

    const that = this;
    this.createStudentForm = this.formBuilder.group({
      name: ['唐金健', [Validators.required]],
      studentID: ['234160501', [Validators.required]],
      mail: ['1271115696@qq.com', [Validators.required]],
      sex: ['男', [Validators.required]],
      nation: ['汉', [Validators.required]],
      birthdate: ['1998-01-14', [Validators.required]],
      identityCard: ['320123199801145011', [Validators.required]],
      className: [that.className, [Validators.required]],
      politicsStatus: ['共青团员', [Validators.required]],
      dorm: ['北十B526', [Validators.required]],
      highSchool: ['南京六合中等专业学校', [Validators.required]],
      adress: [
        '南京市六合区雄州街道王桥路188号桥西苑11栋2908室',
        [Validators.required]
      ],
      tel: ['17512562019', [Validators.required]]
    });
  }

  /**
   * 关闭添加学生的抽屉
   */
  closeCreateStudentDrawer(): void {
    this.createStudentDrawerVisible = false;
  }

  /**
   * 打开编辑学生的抽屉
   */
  openUpdateStudentDrawer(student): void {
    this.updateStudentForm = this.formBuilder.group(student);
    this.updateStudentDrawerVisible = true;
  }

  /**
   * 关闭编辑学生的抽屉
   */
  closeUpdateStudentDrawer(): void {
    this.updateStudentDrawerVisible = false;
  }

  /**
   * 打开发送消息的抽屉
   */
  openSendMessageDrawer(): void {
    this.sendMessageDrawerVisible = true;
  }

  /**
   * 关闭发送消息的抽屉
   */
  closeSendMessageDrawer(): void {
    this.sendMessageDrawerVisible = false;
  }

  /**
   * 添加学生
   * @param createStudentDto 需要添加的学生
   */
  createStudent(createStudentDto: CreateStudentDto) {
    for (const i in this.createStudentForm.controls) {
      if (this.createStudentForm.controls.hasOwnProperty(i)) {
        this.createStudentForm.controls[i].markAsDirty();
        this.createStudentForm.controls[i].updateValueAndValidity();
      }
    }

    this.studentsService.createStudent(createStudentDto).subscribe(
      studentsPostDto => {
        this.fetchStudents();
        this.message.create('success', `添加学生成功`);
        this.restCreateStudentForm();
        this.closeCreateStudentDrawer();
      },
      error => {
        this.message.create(
          'error',
          `${error.error.error}，${error.error.message}`
        );
      }
    );
  }

  /**
   * 编辑学生
   * @param studentsGetDto 需要编辑的学生
   */
  updateStudent(studentsGetDto: StudentsGetDto) {
    for (const i in this.updateStudentForm.controls) {
      if (this.updateStudentForm.controls.hasOwnProperty(i)) {
        this.updateStudentForm.controls[i].markAsDirty();
        this.updateStudentForm.controls[i].updateValueAndValidity();
      }
    }

    this.studentsService
      .updateStudent(studentsGetDto._id, studentsGetDto)
      .subscribe(
        studentsPatchDto => {
          this.fetchStudents();
          this.message.create('success', `保存学生成功`);
          this.restUpdateStudentForm();
          this.closeUpdateStudentDrawer();
        },
        error => {
          this.message.create(
            'error',
            `${error.error.error}，${error.error.message}`
          );
        }
      );
  }

  /**
   * 重置添加学生表单
   * @param e 鼠标事件
   */
  restCreateStudentForm(e?: MouseEvent) {
    if (e) {
      e.preventDefault();
    }
    this.createStudentForm.reset();
    for (const i in this.createStudentForm.controls) {
      if (this.createStudentForm.controls.hasOwnProperty(i)) {
        this.createStudentForm.controls[i].markAsPristine();
        this.createStudentForm.controls[i].updateValueAndValidity();
      }
    }
  }

  /**
   * 重置编辑学生表单
   * @param e 鼠标事件
   */
  restUpdateStudentForm(e?: MouseEvent) {
    if (e) {
      e.preventDefault();
    }
    this.updateStudentForm.reset();
    for (const i in this.updateStudentForm.controls) {
      if (this.updateStudentForm.controls.hasOwnProperty(i)) {
        this.updateStudentForm.controls[i].markAsPristine();
        this.updateStudentForm.controls[i].updateValueAndValidity();
      }
    }
  }

  /**
   * 重置发送消息表单
   * @param e 鼠标事件
   */
  restSendMessageForm(e?: MouseEvent) {
    if (e) {
      e.preventDefault();
    }
    this.sendMessageForm.reset();
    for (const i in this.sendMessageForm.controls) {
      if (this.sendMessageForm.controls.hasOwnProperty(i)) {
        this.sendMessageForm.controls[i].markAsPristine();
        this.sendMessageForm.controls[i].updateValueAndValidity();
      }
    }
  }

  /**
   * 当前页面数据改变时，刷新表头复选框状态
   */
  currentPageDataChange($event: StudentsGetDto[]): void {
    this.listOfDisplayData = $event;
    this.refreshStatus();
  }

  refreshStatus(): void {
    // 如果所有显示的数据，都是选中的，则表头的复选框选中
    this.isAllDisplayDataChecked = this.listOfDisplayData.every(
      item => this.mapOfCheckedId[item._id]
    );
    // 如果所有显示的数据，至少有一个选中，并且不是全部选中，则表头复选框为不确定状态
    this.isIndeterminate =
      this.listOfDisplayData.some(item => this.mapOfCheckedId[item._id]) &&
      !this.isAllDisplayDataChecked;
  }

  checkAll(value: boolean): void {
    this.listOfDisplayData.forEach(
      item => (this.mapOfCheckedId[item._id] = value)
    );
    this.refreshStatus();
  }

  /**
   * 发送消息
   */
  sendMessage({ subject, text }: { subject: string; text: string }) {
    this.studentsService
      .sendMessage({
        to: this.getCheckedStudentMail(),
        subject,
        text
      } as SendMessageDto)
      .subscribe(messagePostDto => {
        this.message.create('success', `成功发送消息`);
        this.closeSendMessageDrawer();
        this.restSendMessageForm();
      });
  }

  private getCheckedStudentMail() {
    const to: string[] = [];

    for (const key in this.mapOfCheckedId) {
      if (this.mapOfCheckedId.hasOwnProperty(key)) {
        const v = this.mapOfCheckedId[key];
        if (v) {
          const r = this.findValueObjectArray(
            this.students,
            '_id',
            key,
            'mail'
          );
          to.push(r);
        }
      }
    }

    return [...new Set(to)];
  }

  private findValueObjectArray(
    o: object[],
    k1: string,
    v1: string,
    k2: string
  ) {
    for (const v of o) {
      if (v[k1] === v1) {
        return v[k2];
      }
    }
    return null;
  }

  search() {
    this.students = this.studentsBak.filter(course => {
      return course.name.indexOf(this.searchValue) !== -1;
    });
  }
}
